package org.craxel.controller;

import java.io.FileInputStream;

import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;

public class Craxel {

	public static void main(final String[] args) {
		
		final String chars = args[0];
		final String excel = args[1];
		
		try {

	        final POIFSFileSystem inp = new POIFSFileSystem(new FileInputStream(excel));
	        
	        StringBuilder builder;
	        
	        long start = System.currentTimeMillis();
	        
	        
	        // 1
	        System.out.println("Checking length 1");
	        for(int a = 0; a < chars.length(); a++){
	        	System.out.print("* ");
	        	builder = new StringBuilder();
	        	builder.append(chars.charAt(a));
	        	
	        	if(checkPassword(builder.toString(), inp)){
	        		System.out.println("\nFOUND: " + builder.toString());
	        		return;
	        	}
	        }
	        
	        //2
	        System.out.println("\nChecking length 2");
	        for(int a = 0; a < chars.length(); a++){
	        	System.out.print("* ");
	        	for(int b = 0; b < chars.length(); b++){
	        		builder = new StringBuilder();
		        	builder.append(chars.charAt(a));
	        		builder.append(chars.charAt(b));
		        	
		        	if(checkPassword(builder.toString(), inp)){
		        		System.out.println("\nFOUND: " + builder.toString());
		        		return;
		        	}
	        	}
	        }

	        
	        //3
	        System.out.println("\nChecking length 3");
	        for(int a = 0; a < chars.length(); a++){
	        	System.out.print("* ");
	        	for(int b = 0; b < chars.length(); b++){
	        		for(int c = 0; c < chars.length(); c++){
		        		builder = new StringBuilder();
			        	builder.append(chars.charAt(a));
		        		builder.append(chars.charAt(b));
		        		builder.append(chars.charAt(c));
			        	
			        	if(checkPassword(builder.toString(), inp)){
			        		System.out.println("\nFOUND: " + builder.toString());
			        		return;
			        	}
	        		}
	        	}
	        }
	        
	        //4
	        System.out.println("\nChecking length 4");
	        for(int a = 0; a < chars.length(); a++){
	        	System.out.print("* ");
	        	for(int b = 0; b < chars.length(); b++){
	        		for(int c = 0; c < chars.length(); c++){
	        			for(int d = 0; d < chars.length(); d++){
			        		builder = new StringBuilder();
				        	builder.append(chars.charAt(a));
			        		builder.append(chars.charAt(b));
			        		builder.append(chars.charAt(c));
			        		builder.append(chars.charAt(d));
				        	
				        	if(checkPassword(builder.toString(), inp)){
				        		System.out.println("\nFOUND: " + builder.toString());
				        		return;
				        	}
	        			}
	        		}
	        	}
	        }
	        
	        printStatistics(chars, start, 4);
	        
	        //5
	        System.out.println("\nChecking length 5");
	        for(int a = 0; a < chars.length(); a++){
	        	System.out.print("* ");
	        	for(int b = 0; b < chars.length(); b++){
	        		for(int c = 0; c < chars.length(); c++){
	        			for(int d = 0; d < chars.length(); d++){
	        				for(int e = 0; e < chars.length(); e++){
				        		builder = new StringBuilder();
					        	builder.append(chars.charAt(a));
				        		builder.append(chars.charAt(b));
				        		builder.append(chars.charAt(c));
				        		builder.append(chars.charAt(d));
				        		builder.append(chars.charAt(e));
					        	
					        	if(checkPassword(builder.toString(), inp)){
					        		System.out.println("\nFOUND: " + builder.toString());
					        		return;
					        	}
	        				}
	        			}
	        		}
	        	}
	        }
	        
	        printStatistics(chars, start, 5);
	        
	        //6
	        System.out.println("\nChecking length 6");
	        for(int a = 0; a < chars.length(); a++){
	        	System.out.print("* ");
	        	for(int b = 0; b < chars.length(); b++){
	        		for(int c = 0; c < chars.length(); c++){
	        			for(int d = 0; d < chars.length(); d++){
	        				for(int e = 0; e < chars.length(); e++){
	        					for(int f = 0; f < chars.length(); f++){
					        		builder = new StringBuilder();
						        	builder.append(chars.charAt(a));
					        		builder.append(chars.charAt(b));
					        		builder.append(chars.charAt(c));
					        		builder.append(chars.charAt(d));
					        		builder.append(chars.charAt(e));
					        		builder.append(chars.charAt(f));
						        	
						        	if(checkPassword(builder.toString(), inp)){
						        		System.out.println("\nFOUND: " + builder.toString());
						        		return;
						        	}
	        					}
	        				}
	        			}
	        		}
	        	}
	        }
	        
	        printStatistics(chars, start, 6);
	        
	        //7
	        System.out.println("\nChecking length 7");
	        for(int a = 0; a < chars.length(); a++){
	        	System.out.print("* ");
	        	for(int b = 0; b < chars.length(); b++){
	        		for(int c = 0; c < chars.length(); c++){
	        			for(int d = 0; d < chars.length(); d++){
	        				for(int e = 0; e < chars.length(); e++){
	        					for(int f = 0; f < chars.length(); f++){
	        						for(int g = 0; g < chars.length(); g++){
						        		builder = new StringBuilder();
							        	builder.append(chars.charAt(a));
						        		builder.append(chars.charAt(b));
						        		builder.append(chars.charAt(c));
						        		builder.append(chars.charAt(d));
						        		builder.append(chars.charAt(e));
						        		builder.append(chars.charAt(f));
						        		builder.append(chars.charAt(g));
							        	
							        	if(checkPassword(builder.toString(), inp)){
							        		System.out.println("\nFOUND: " + builder.toString());
							        		return;
							        	}
	        						}
	        					}
	        				}
	        			}
	        		}
	        	}
	        }
	        
	        printStatistics(chars, start, 7);
	        
	        //8
	        System.out.println("\nChecking length 8");
	        for(int a = 0; a < chars.length(); a++){
	        	System.out.print("* ");
	        	for(int b = 0; b < chars.length(); b++){
	        		for(int c = 0; c < chars.length(); c++){
	        			for(int d = 0; d < chars.length(); d++){
	        				for(int e = 0; e < chars.length(); e++){
	        					for(int f = 0; f < chars.length(); f++){
	        						for(int g = 0; g < chars.length(); g++){
	        							for(int h = 0; h < chars.length(); h++){
							        		builder = new StringBuilder();
								        	builder.append(chars.charAt(a));
							        		builder.append(chars.charAt(b));
							        		builder.append(chars.charAt(c));
							        		builder.append(chars.charAt(d));
							        		builder.append(chars.charAt(e));
							        		builder.append(chars.charAt(f));
							        		builder.append(chars.charAt(g));
							        		builder.append(chars.charAt(h));
								        	
								        	if(checkPassword(builder.toString(), inp)){
								        		System.out.println("\nFOUND: " + builder.toString());
								        		return;
								        	}
	        							}
	        						}
	        					}
	        				}
	        			}
	        		}
	        	}
	        }
	        
	        printStatistics(chars, start, 8);
	        
	        //9
	        System.out.println("\nChecking length 9");
	        for(int a = 0; a < chars.length(); a++){
	        	System.out.print("* ");
	        	for(int b = 0; b < chars.length(); b++){
	        		for(int c = 0; c < chars.length(); c++){
	        			for(int d = 0; d < chars.length(); d++){
	        				for(int e = 0; e < chars.length(); e++){
	        					for(int f = 0; f < chars.length(); f++){
	        						for(int g = 0; g < chars.length(); g++){
	        							for(int h = 0; h < chars.length(); h++){
	        								for(int i = 0; i < chars.length(); i++){
								        		builder = new StringBuilder();
									        	builder.append(chars.charAt(a));
								        		builder.append(chars.charAt(b));
								        		builder.append(chars.charAt(c));
								        		builder.append(chars.charAt(d));
								        		builder.append(chars.charAt(e));
								        		builder.append(chars.charAt(f));
								        		builder.append(chars.charAt(g));
								        		builder.append(chars.charAt(h));
								        		builder.append(chars.charAt(i));
									        	
									        	if(checkPassword(builder.toString(), inp)){
									        		System.out.println("\nFOUND: " + builder.toString());
									        		return;
									        	}
	        								}
	        							}
	        						}
	        					}
	        				}
	        			}
	        		}
	        	}
	        }
	        
	        printStatistics(chars, start, 9);
	        
	        //10
	        System.out.println("\nChecking length 10");
	        for(int a = 0; a < chars.length(); a++){
	        	System.out.print("* ");
	        	for(int b = 0; b < chars.length(); b++){
	        		for(int c = 0; c < chars.length(); c++){
	        			for(int d = 0; d < chars.length(); d++){
	        				for(int e = 0; e < chars.length(); e++){
	        					for(int f = 0; f < chars.length(); f++){
	        						for(int g = 0; g < chars.length(); g++){
	        							for(int h = 0; h < chars.length(); h++){
	        								for(int i = 0; i < chars.length(); i++){
	        									for(int l = 0; l < chars.length(); l++){
									        		builder = new StringBuilder();
										        	builder.append(chars.charAt(a));
									        		builder.append(chars.charAt(b));
									        		builder.append(chars.charAt(c));
									        		builder.append(chars.charAt(d));
									        		builder.append(chars.charAt(e));
									        		builder.append(chars.charAt(f));
									        		builder.append(chars.charAt(g));
									        		builder.append(chars.charAt(h));
									        		builder.append(chars.charAt(i));
									        		builder.append(chars.charAt(l));
										        	
										        	if(checkPassword(builder.toString(), inp)){
										        		System.out.println("\nFOUND: " + builder.toString());
										        		return;
										        	}
	        									}
	        								}
	        							}
	        						}
	        					}
	        				}
	        			}
	        		}
	        	}
	        }
	        
	        printStatistics(chars, start, 10);
	        
	    } catch (Exception e) {
	       e.printStackTrace();
	    }

	}

	private static boolean checkPassword(String password, final POIFSFileSystem  inp) {
		try{
			Biff8EncryptionKey.setCurrentUserPassword(password); 
			new HSSFWorkbook(inp);
			Biff8EncryptionKey.setCurrentUserPassword(null); 
			return true;
		} catch (Exception ex){
			Biff8EncryptionKey.setCurrentUserPassword(null); 
			return false;
		}
	}
	
	private static void printStatistics(final String alphabet, final long start, final int size){
		double computed = 0.0D;
		
		for(int i = 1; i <= size; i++){
			computed += Math.pow(alphabet.length(), i);
		}
		
		long diff = (System.currentTimeMillis()-start);
		
		long seconds = diff/1000;
		long s = seconds%60;
		long minutes = seconds/60;
		long m = minutes%60;
		long hours = minutes/60;
		long h = hours%24;
		long days = hours/24;
		
		double perSecond = computed / (seconds);
        
        System.out.print(" " + ((int)Math.floor(days)) + "d " + ((int)Math.floor(h)) +
        		"h " + ((int)Math.floor(m)) + "m " + ((int)Math.floor(s)) +
        		"s" + " average per second: " + ((int)Math.floor(perSecond)) + " attempts" );
	}

}
